package se.webbzon.boltzmann.editor.factory.propertyframe;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import se.webbzon.boltzmann.editor.component.dependencylist.DependencyComboBox;
import se.webbzon.boltzmann.editor.component.itemlist.ItemList;
import se.webbzon.boltzmann.editor.mvc.EditorModel;
import se.webbzon.boltzmann.editor.propertyframe.WorldObjectPropertyFrame;
import se.webbzon.boltzmann.game.object.action.ShakeAction;
import se.webbzon.boltzmann.game.object.action.ShakeActionLoot;
import se.webbzon.boltzmann.item.ItemGroup;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;

public class ShakeActionPropertyFrameFactory implements PropertyFrameFactory {

	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public String getWorldObjectName() {
		return ShakeAction.worldObjectName;
	}

	@Override public WorldObjectPropertyFrame makePropertyFrame(EditorModel model,
																WorldObject instance) {
		return new PropertyFrameImpl(model, (ShakeAction) instance);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private static final class PropertyFrameImpl extends WorldObjectPropertyFrame {

		// The input fields for this property frame
		private final JTextField idInput, rangeInput, amountInput;
		
		// The combo boxes of this property frame
		private final DependencyComboBox<WorldStaticObject> parentInput;
		
		// The check boxes of this property frame
		private final JCheckBox frontOnlyInput, gamePersistentInput, regionPersistentInput;
		
		// The combo boxes of this property frame
		private final JComboBox<ShakeActionLoot> lootInput;
		
		// The item list of this property frame
		private final ItemList itemInput;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public PropertyFrameImpl(EditorModel model, ShakeAction action) {
			super(model, action);
			
			// Create action panel
			JPanel actionPanel = new JPanel();
			actionPanel.setLayout(new BoxLayout(actionPanel,BoxLayout.Y_AXIS));
			
			// Create id panel
			JPanel idPanel = new JPanel();
			idPanel.setBorder(BorderFactory.createTitledBorder("Object Id:"));
			idPanel.setLayout(new GridLayout(1,2));
			idPanel.add(new JButton(new RandomizeAction(this)));
			idInput = new JTextField("" + action.getId());
			idPanel.add(idInput);
			actionPanel.add(idPanel);
			
			// Create configuration panel
			JPanel configPanel = new JPanel();
			configPanel.setBorder(BorderFactory.createTitledBorder("Action Configuration:"));
			configPanel.setLayout(new BoxLayout(configPanel,BoxLayout.Y_AXIS));
			
			JPanel upperConfigPanel = new JPanel();
			upperConfigPanel.setLayout(new GridLayout(7,2));
			
			upperConfigPanel.add(new JLabel("Action Range:"));
			rangeInput = new JTextField("" + action.getRange());
			upperConfigPanel.add(rangeInput);
			upperConfigPanel.add(new JLabel("Parent:"));
			parentInput = 
					new DependencyComboBox<WorldStaticObject>(	model,
																WorldStaticObject.class,
																action.getParent());
			upperConfigPanel.add(parentInput);
			upperConfigPanel.add(new JLabel("Front Only:"));
			frontOnlyInput = new JCheckBox();
			frontOnlyInput.setSelected(action.getFrontOnly());
			upperConfigPanel.add(frontOnlyInput);
			upperConfigPanel.add(new JLabel("Game Persistent:"));
			gamePersistentInput = new JCheckBox();
			gamePersistentInput.setSelected(action.isGamePersistent());
			upperConfigPanel.add(gamePersistentInput);
			upperConfigPanel.add(new JLabel("Region Persistent:"));
			regionPersistentInput = new JCheckBox();
			regionPersistentInput.setSelected(action.isRegionPersistent());
			upperConfigPanel.add(regionPersistentInput);
			upperConfigPanel.add(new JLabel("Loot:"));
			lootInput = new JComboBox<ShakeActionLoot>(ShakeActionLoot.values());
			lootInput.setSelectedItem(action.getLoot());
			upperConfigPanel.add(lootInput);
			upperConfigPanel.add(new JLabel("Amount/Item id:"));
			amountInput = new JTextField();
			upperConfigPanel.add(amountInput);
			configPanel.add(upperConfigPanel);
			
			JPanel lowerConfigPanel = new JPanel();
			lowerConfigPanel.setLayout(new GridLayout(1,2));
			
			lowerConfigPanel.add(new JLabel("Item:"));
			itemInput = new ItemList();
			lowerConfigPanel.add(itemInput);
			configPanel.add(lowerConfigPanel);
			
			actionPanel.add(configPanel);
			addPanel("Action",actionPanel);
			
			Listener listener = new Listener(this);
			lootInput.addItemListener(listener);
			lootInput.addActionListener(listener);
			updateConfigPanel();
			
			initialize();
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public boolean apply(Collection<String> errorMessages) {
			try {
				ShakeAction action = (ShakeAction) getInstance();
				final double range = Double.parseDouble(rangeInput.getText());
				action.setId(Long.parseLong(idInput.getText()));
				action.setFrontOnly(frontOnlyInput.isSelected());
				action.setRange(range);
				action.setParent(parentInput.getInstance());
				action.setGamePersistent(gamePersistentInput.isSelected());
				action.setRegionPersistent(regionPersistentInput.isSelected());
				action.setLoot((ShakeActionLoot) lootInput.getSelectedItem());
				if (lootInput.getSelectedItem() == ShakeActionLoot.ITEM)
					action.setAmount(ItemGroup.instance().getId(itemInput.getItem()));
				else
					action.setAmount(Integer.parseInt(amountInput.getText()));
				updateConfigPanel();
				return true;
			} catch (NumberFormatException e) {
				errorMessages.add(e.getMessage());
				return false;
			}
		}
		
		/*============================================================
		Private Methods
		============================================================*/
		
		private final void updateConfigPanel() {
			ShakeAction action = (ShakeAction) getInstance();
			if (lootInput.getSelectedItem() == ShakeActionLoot.ITEM) {
				itemInput.setEnabled(true);
				amountInput.setEnabled(false);
			} else {
				itemInput.setEnabled(false);
				amountInput.setEnabled(true);
			}
			itemInput.setItem(ItemGroup.instance().getItem(action.getAmount()));
			amountInput.setText("" + action.getAmount());
		}
		
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private static final class RandomizeAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = -4293223962815772545L;
		
		// The property frame associated with this action
		private final PropertyFrameImpl frame;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public RandomizeAction(PropertyFrameImpl frame) {
			this.frame = frame;
			putValue(AbstractAction.NAME, "ID (press to randomize):");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent arg0) {
			long id = new Random().nextLong();
			frame.idInput.setText("" + id);
		}
		
	}
	
	private static final class Listener implements ItemListener, ActionListener {
		
		// The property frame associated with this action
		private final PropertyFrameImpl frame;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public Listener(PropertyFrameImpl frame) {
			this.frame = frame;
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent arg0) {
			frame.updateConfigPanel();
		}

		@Override public void itemStateChanged(ItemEvent arg0) {
			frame.updateConfigPanel();
		}
		
	}

}
